import { defineStore } from 'pinia'
import { store } from '../index'
import { h } from 'vue'
import { ElNotification, ElMessage } from 'element-plus'
import { getTableList, editTableData } from '@/api/basic'
import { MetaTable } from '@/modules/meta'
import SharedSocket from '@/utils/SharedSocket.js'
import { useCache } from '@/hooks/web/useCache'

const { wsCache } = useCache()

export interface NotificationState {
  worker: any
  count: number
  config: Array<any>
  datas: Array<any>
  notifications: Array<any>
  notificationInstances: Object
}

export const useNotificationStore = defineStore('notification', {
  state: (): NotificationState => ({
    worker: null,
    count: 0,
    config: [],
    datas: [],
    notifications: [],
    notificationInstances: {}
  }),
  getters: {
    getConfig(): Array<any> {
      return this.config
    },
    getNotificationInstances(): Object {
      return this.notificationInstances
    },
    getNotifications(): Array<any> {
      return this.notifications
    },
    getCount(): number {
      return this.count
    }
  },
  actions: {
    initSocket(): void {
      if (!this.config || this.config.length < 1) {
        return
      }
      const token = wsCache.get('Admin-Token')
      let wsUrl = location.origin.replace('http', 'ws')
      if (['localhost'].includes(location.hostname)) {
        wsUrl = import.meta.env.VITE_WS_TEST_URL
      }
      const worker = new SharedSocket(`${wsUrl}/ws?token=${token}`)
      worker.onmessage((data) => {
        console.log(data) // 打印接收到的内容
        if (data && data != 'ok') {
          this.fetchData()
        }
      })
      this.worker = worker
    },
    setConfig(config: Array<any>): void {
      this.config = config
      try {
        this.initSocket()
      } catch (e) {
        console.error(e)
      }
      this.fetchData()
    },
    async fetchData(key?: any): Promise<any> {
      if (!this.config || this.config.length < 1) {
        return
      }
      const fetchData = this.fetchData
      const configs = this.config.filter((c) => c?.meta?.source)
      const queryList = configs.map((c) =>
        getTableList({
          filter: c?.filter,
          conditions: {},
          page: 1,
          size: 20,
          source: c.meta.source
        })
      )
      const allDatas = await Promise.all(queryList)
      // 总消息数
      this.count = allDatas.reduce((t, c) => {
        t += c.data?.length || 0
        return t
      }, 0)
      this.notifications = configs.map(function (c, i) {
        return {
          key: c.key,
          title: c.title,
          source: c.meta.source,
          fields: c.meta.fields,
          data: allDatas[i]?.data || [],
          count: allDatas[i]?.data?.length || 0,
          instance: null,
          show(nt, ns) {
            if (ns[nt.key]) {
              ns[nt.key].close()
            }
            if (nt.count < 1) {
              return
            }
            ns[nt.key] = ElNotification({
              title: nt.title,
              message: h(MetaTable, {
                meta: this.fields,
                list: this.data,
                showSelect: false,
                showOperation: false,
                config: {
                  'show-overflow': 'tooltip',
                  height: 'auto',
                  'keep-source': true,
                  'edit-config': { trigger: 'click', mode: 'cell', showStatus: true }
                },
                async onEditSave(form) {
                  await editTableData({ source: nt.source, fields: form })
                  ElMessage.success('保存成功')
                  fetchData(nt.key)
                }
              }),
              duration: 0,
              position: 'bottom-right',
              customClass: 'my-notification'
            })
          }
        }
      })
      this.notifications
        .filter((t) => (key ? t.key === key : true))
        .forEach((t, i) => {
          setTimeout(() => {
            t.show(t, this.notificationInstances)
          }, i * 500)
        })
    },
    close(key?: any): void {
      if (key) {
        this.getNotificationInstances[key]?.close()
      } else {
        Object.values(this.getNotificationInstances).forEach((ins) => {
          ins.close()
        })
        // 退出登录时，关闭websocket
        if (this.worker) {
          this.worker.close()
        }
      }
    }
  }
})

export const useNotificationStoreWithOut = () => {
  return useNotificationStore(store)
}
